﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;



using SistemaCenterQuimPost.Plantillas;

using System.Threading; //usado para el proceso batch de actuliazar precios.

using System.IO;    //3 referencias que son necesarias para el proceso de archivos.
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

using SistemaCenterQuimPost.Entidad; //necesario para crear instancias de RegistroUsuario y RegistroListaPrecio en el proceso de archivos.


namespace SistemaCenterQuimPost.UI.PostCajero
{
    public partial class frmCargarRegistrosProductos : SistemaCenterQuimPost.Plantillas.frmPlantillaHijo
    {
        //---------ATRIBUTOS--------------------
        private DataSet2 centerQuimDs;  //variables que me permitirán acceder a la base de datos.
        private DataSet2TableAdapters.ProductosTableAdapter productoTa;
        private StringBuilder errores;


        //objeto para serializar los RegistroUsuario y RegistroListaPrecio en formato binario
        private BinaryFormatter aplicadorFormato = new BinaryFormatter(); //Clase que permite deserializar objeto, es decir pasarlo a objeto desde binario.
        private FileStream registrosProductosE; //clase que maneja la información sobre el archvi y la forma de abrirlo.

        //---------CONSTRUCTORES---------------
        public frmCargarRegistrosProductos()
        {
            InitializeComponent();


            centerQuimDs = new DataSet2();  //variables que me permitirán acceder a la base de datos.
            productoTa = new DataSet2TableAdapters.ProductosTableAdapter();

            errores = new StringBuilder();

        }

        //----------ESTADOS----------------------
        private void frmCargarRegistrosProductos_Load(object sender, EventArgs e)
        {
            lblError.Visible = false; //al ser un formulario sin estado, este atributo se lee en este lugar.

            txtInformeErrores.Text = ""; //se vacia el cuadro de errores.

            obtenerArchivosActualizaciones(); //carga el cboArchivo con los archivos.

            cboActualizadores.SelectedItem = 0; //coloca como primer opcion el primer archivo en el comboBox.

        }

        //------METODOS VARIOS------------------
        
        private void btnProcesar_Click(object sender, EventArgs e)
        {
            if (cboActualizadores.Items.Count > 0)
            {
                DialogResult result = MessageBox.Show("¿Está seguro que desea actualizar los precios de los productos? ", "ACTUALIZACION DE PRECIOS", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                if (result == DialogResult.Yes)
                {
                    lblEspere.Visible = true;

                    this.Enabled = false; //el formulario se deshabilita mientras actualiza la lista de precios. Es proceso Batch

                    Thread unHilo = new Thread(new ThreadStart(cargarProductos));
                    unHilo.Priority = ThreadPriority.Highest;
                    unHilo.Start();  //Se ejecuta el hilo para actualizar el atributo ResgProductos
                     
                }

            }
            else
            {

                DialogResult result = MessageBox.Show("No posee actualizadores de precios disponibles.", "ACTUALIZACION DE PRECIOS", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }



        }

        private void cargarProductos()  //actualizamos los precios de los productos. Luego elimina el archivo por seguridad
        {

            string nombreArchivo = "C:\\Dropbox\\Datos del Sistema\\Registros Productos\\" + cboActualizadores.SelectedItem.ToString();

            //guardar el archivo a través del objeto FileStream.
            try
            {
                this.registrosProductosE = new FileStream(nombreArchivo, FileMode.Open, FileAccess.Read); //crea el objeto FileStream para obtener acceso de lectura al archivo.

                LeerDatos();

                //cuando ya no tiene más datos se lanza la excepcion SerializationException para informar que terminó.

            }

            catch (SerializationException)
            {
                this.Enabled = true;  //el formulario se habilita luego de actualizar la lista de precios. Es proceso Batch
                lblEspere.Visible = false;

                if (errores.Length == 0)
                {
                    errores.AppendLine("TODOS LOS PRODUCTOS FUERON CARGADOS SIN ERRORES.");
                    txtInformeErrores.Text = errores.ToString();
                }
                else
                {
                    txtInformeErrores.Text = errores.ToString();
                }
                
                MessageBox.Show("Productos ingresados con exitos!!", "CARGA DE PRODUCTOS", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            catch (FormatException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("Formato inválido", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }

            catch (IOException)
            {
                //notifica al usuario si el archivo no existe
                MessageBox.Show("El archivo de lista de precio no se encuentra. \n\n Solicitela a casa central.", "ACTUALIZACION DE PRECIOS", MessageBoxButtons.OK, MessageBoxIcon.Information);

                this.Enabled = true; //el formulario se habilita luego de actualizar la lista de precios.

                lblEspere.Visible = false;
            }

            catch (Exception ex)
            {
                //Por cualquier otra excepcion se informa el error, en este caso es un error grave.
                MessageBox.Show("La conexión a la base de datos no fué exitosa. /n /n Comuniquese con su desarrollador para solucionar el problema /n /n" + ex.Message, "ERROR GRAVE - ACCESO A BASE DE DATO", MessageBoxButtons.OK, MessageBoxIcon.Error);

                this.Close();
            }

            finally
            {
                cerrarArchivo();

                File.Delete("C:\\Dropbox\\Datos del Sistema\\Lista de Precios\\ListaPrecios.cq"); //eliminamos el archivo.
            }
        }

        private void LeerDatos()
        {
            
            do
            {           //instanciamos unRegistroListaPrecio(Serializado) para ir capturando los objetos del archivo.
                RegistroActualizacionProductos unRegistroActualizacion = (RegistroActualizacionProductos)aplicadorFormato.Deserialize(registrosProductosE);

                //buscamos el producto y verificamos si hubo cambios en los precios.
                productoTa.FillByNombre(centerQuimDs.Productos, unRegistroActualizacion.Descripcion);

                if (centerQuimDs.Productos.Rows.Count == 0) //si no existe el producto
                {
                    if (unRegistroActualizacion.Tipo == "D" ) //es un disuelto
                    {
                        productoTa.FillByNombre(centerQuimDs.Productos, unRegistroActualizacion.BaseDescripcion); //busca si existe la base en los registros locales

                        if (centerQuimDs.Productos.Rows.Count != 0) //si existe la base localmente.
                        {
                            productoTa.InsertQueryProducto(unRegistroActualizacion.CodProducto, unRegistroActualizacion.Descripcion, Convert.ToDecimal(Math.Round(unRegistroActualizacion.PrecioCosto,2)), Convert.ToDecimal(Math.Round(unRegistroActualizacion.PrecioVenta,2)), Convert.ToDecimal(unRegistroActualizacion.StockActual), Convert.ToDecimal(unRegistroActualizacion.CantidadMinima), unRegistroActualizacion.Tipo, unRegistroActualizacion.BaseCodigo, unRegistroActualizacion.BaseDescripcion, Convert.ToDecimal(unRegistroActualizacion.LitrosEnvase), unRegistroActualizacion.Porcentaje, true,Convert.ToDateTime(unRegistroActualizacion.Fecha));
                            
                        }

                        else
                        {
                            errores.AppendLine("PRODUCTO: "+ unRegistroActualizacion.Descripcion + "- NO FUE INGRESADO - NO EXISTE BASE");
                        }

                    } else //si localmente no existe y es una base o terminado, solo se ingresa.
                    {
                        productoTa.InsertQueryProducto(unRegistroActualizacion.CodProducto, unRegistroActualizacion.Descripcion, Convert.ToDecimal(Math.Round(unRegistroActualizacion.PrecioCosto, 2)), Convert.ToDecimal(Math.Round(unRegistroActualizacion.PrecioVenta, 2)), Convert.ToDecimal(unRegistroActualizacion.StockActual), Convert.ToDecimal(unRegistroActualizacion.CantidadMinima), unRegistroActualizacion.Tipo, unRegistroActualizacion.BaseCodigo, unRegistroActualizacion.BaseDescripcion, Convert.ToDecimal(unRegistroActualizacion.LitrosEnvase), unRegistroActualizacion.Porcentaje, true, Convert.ToDateTime(unRegistroActualizacion.Fecha));
                          
                    }
                }else
                {
                    errores.AppendLine("PRODUCTO: " + unRegistroActualizacion.Descripcion + "- NO FUE CARGADO - YA EXISTE");
                }

            } while (registrosProductosE != null);

        }


        private void cerrarArchivo()
        {
            try
            {
                if (registrosProductosE != null)  //determina si existe el archivo
                {
                    registrosProductosE.Close();  //cierra el archivo

                    File.Delete(registrosProductosE.Name); //eliminamos el archivo.

                    obtenerArchivosActualizaciones(); //se vuelve a actualizar el combo.
                }
            }
            catch (IOException)  //notifica al usuario del error al cerrar el archivo
            {
                MessageBox.Show("No se puede cerrar el archivo.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            }
        }

        private string obtenerFechaActual()  //Dato necesario para el alta de venta
        {
            frmPlantillaPadre unFrm = (frmPlantillaPadre)this.MdiParent;
            return unFrm.getFechaActual();
        }

        private void obtenerArchivosActualizaciones()  //carga en el cboActualizadores los archivos de actualizaciones de precios disponibles.
        {
            this.cboActualizadores.Items.Clear(); //borra todo lo que tenía antes. 

            string directorioPrecios = "C:\\Dropbox\\Datos del Sistema\\Registros Productos"; //seteamos el directorio desde donde leeremos los archivos

            foreach (string archivo in Directory.GetFiles(directorioPrecios))  //por cada archvio en este directorio
            {
                FileInfo archivoInfo = new FileInfo(archivo);  //obtenemos información de ese directorio

                cboActualizadores.Items.Add(archivoInfo.Name); //mostramos solo su nombre corto.

            }

        }

    }
}
